﻿#pragma once
#include "OCMain/FileUtil.h"
#include "OCMain/Log.h"
#include "OCMain/OCMath.h"
#include "OCMain/ZipUtil.h"
#include "OCMain/zip/gzstream.h"
#include "json/json.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

using namespace OCPP;

void CSVToJson_main(String fileName, String output1, uint32 skipLines = 0)
{
	String path = FileUtil::getFilePath(fileName);
	if (output1.empty()) {
		output1 = joinPath(path, "json");
	}
	String output = output1;

	FileUtil::makeDirectory(output);
	std::ifstream ifs(fileName);
	if (ifs)
	{
		String line;
		uint32 count = 0;
		std::map<uint32, std::vector<double> > mapData;
		while (skipLines != 0)
		{
			getline(ifs, line);
			skipLines--;
		}

		float minX = Math::POS_INFINITY;
		float minY = Math::POS_INFINITY;
		float minZ = Math::POS_INFINITY;
		float maxX = Math::NEG_INFINITY;
		float maxY = Math::NEG_INFINITY;
		float maxZ = Math::NEG_INFINITY;

		while (getline(ifs, line))
		{
			StringUtil::trim(line);
			StringVector strVec1 = StringUtil::split(line, " ");
			if (strVec1.empty())
			{
				break;
			}

			StringVector strVec;
			for (auto& f : strVec1)
			{
				if (!f.empty()) strVec.push_back(f);
			}

			if (strVec.size() != 4)
			{
				OCPP_LOG_ERROR << "line error:" << strVec.size() << "\n";
				break;
			}

			float x = std::stof(strVec[0].c_str());
			float y = std::stof(strVec[1].c_str());
			int t = std::stoi(strVec[2].c_str());
			float z = std::stof(strVec[3].c_str());

			minX = std::min(x, minX);
			minY = std::min(y, minY);
			minZ = std::min(z, minZ);
			maxX = std::max(x, maxX);
			maxY = std::max(y, maxY);
			maxZ = std::max(z, maxZ);

			mapData[t].push_back(x);
			mapData[t].push_back(y);
			mapData[t].push_back(z);
			count++;
		}

		for (const auto& [first, second] : mapData)
		{
			OCPP_LOG_INFO << "Time:" << first << "\tnum:" << second.size() << "\n";

			rapidjson::StringBuffer buffer;
			rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);

			writer.StartObject();
			writer.Key("minX");
			writer.Double(minX);
			writer.Key("minY");
			writer.Double(minY);
			writer.Key("minZ");
			writer.Double(minZ);
			writer.Key("maxX");
			writer.Double(maxX);
			writer.Key("maxY");
			writer.Double(maxY);
			writer.Key("maxZ");
			writer.Double(maxZ);

			writer.Key("data");
			writer.StartArray();
			writer.SetMaxDecimalPlaces(8);
			for (const auto& d : second)
			{
				writer.Double(d);
			}
			writer.EndArray();
			writer.EndObject();

			String name = str_format("%d.json.gz", first);
			ogzstream ofs(joinPath(output, name).c_str());
			ofs << buffer.GetString();
			ofs.close();
		}
	}
}

void areaJson(String path)
{
	int width = 256;
	int height = width;

	FloatVector data;
	data.resize(width * height);

	float minX = Math::POS_INFINITY;
	float minY = Math::POS_INFINITY;
	float minZ = Math::POS_INFINITY;
	float maxX = Math::NEG_INFINITY;
	float maxY = Math::NEG_INFINITY;
	float maxZ = Math::NEG_INFINITY;

	uint64 area = 0;

	Json::Value outObj;

	for (int i = 0; i <= 180; i++)
	{
		Json::Value jsonObj;
		String jsonContetnt;
		String fileName = joinPath(path, str_format("%d.json", i));
		if (FileUtil::existFile(fileName))
		{
			String bin = FileUtil::getFileText(fileName);
			Json::Reader reader;
			if (!reader.parse(bin, jsonObj))
			{
				OCPP_LOG_ERROR << fileName << " error json.\n";
			}
		}
		else
		{
			fileName += ".gz";
			String bin = FileUtil::getFileText(fileName);
			Json::Reader reader;
			reader.parse(ZipUtil::gzipDecompress(bin), jsonObj);
		}

		bool isArray = jsonObj.isArray();
		Json::Value dataObj = isArray ? jsonObj : jsonObj["data"];

		
		if (i == 0)
		{
			if (!isArray)
			{
				minX = jsonObj["minX"].asFloat() - 1;
				minY = jsonObj["minY"].asFloat() - 1;
				maxX = jsonObj["maxX"].asFloat() + 1;
				maxY = jsonObj["maxY"].asFloat() + 1;
				area = (maxX - minX) * (maxY - minY);
			}
			else
			{
				for (auto i = 0; i < dataObj.size(); i += 3)
				{
					float x = dataObj[i].asFloat();
					float y = dataObj[i + 1].asFloat();
					float z = dataObj[i + 2].asFloat();
					minX = std::min(minX, x);
					minY = std::min(minY, y);
					maxX = std::max(maxX, x);
					maxY = std::max(maxY, y);
				}

				area = (maxX - minX) * (maxY - minY);
			}
		}

		for (auto i = 0; i < dataObj.size(); i += 3)
		{
			float x = dataObj[i].asFloat();
			float y = dataObj[i + 1].asFloat();
			float z = dataObj[i + 2].asFloat();
			minZ = std::min(z, minZ);
			maxZ = std::max(z, maxZ);
			if (z != 0.0)
			{
				int c = (x - minX) / (maxX - minX) * width;
				int r = (y - minY) / (maxY - minY) * width;
				int index = r * width + c;
				if (data[index] == 0.0f)
				{
					data[index] = z;
				}
			}
		}
		uint32 effectCellCount = 0;
		for (auto& z : data)
		{
			if (z != 0.0f)
			{
				effectCellCount++;
			}
		}
		uint64 effectArea = area * effectCellCount / (width * height);
		OCPP_LOG_INFO << effectCellCount << "\t" << effectArea << "\n";
		Json::Value obj;
		obj["minZ"] = minZ;
		obj["maxZ"] = maxZ;
		obj["area"] = effectArea;
		outObj.append(obj);
	}

	std::ofstream ofs(joinPath(path, "area.json"));
	ofs << outObj.toStyledString();
	ofs.close();
}

#if 0
void  CSVToJson()
{
	String path = U2A("\\\\10.104.207.155\\Assets\\Sanxia\\yonglang\\xp");
	areaJson(path);
}
#endif

#if 1
void  CSVToJson()
{
	String path = U2A("F:\\opt\\屈原祠");

	StringVector sv = FileUtil::findFiles(path);

	//for (auto& f : sv)
	//{
	//	if (f == "." || f == "..") continue;
	//	String output = StringUtil::replaceAll(f, "wave all as time", "");
	//	output = StringUtil::replaceAll(output, "landslide thickness all", "");
	//	output = StringUtil::replaceAll(output, ".txt", "");
	//	String fileName = joinPath(path, f);
	//	CSVToJson_main(fileName, joinPath(path, output));
	//}

	for (auto& f : sv)
	{
		if (f == "." || f == "..") continue;
		StringVector fs = StringUtil::split(StringUtil::replaceAll(f, U2A("年"), ""), " ");
		if (fs.size() < 2) continue;
		//if (!StringUtil::contains(f, U2A("年"))) continue;
		String output = StringUtil::replaceAll(f, "wave all as time", "");
		output = StringUtil::replaceAll(output, "landslide thickness all", "");
		output = StringUtil::replaceAll(output, ".txt", "");
		String fileName1 = joinPath(path, f, "wave all as time.txt");
		String fileName2 = joinPath(path, f, "landslide thickness all.txt");
		OCPP_LOG_INFO << fileName1 << "\n";
		OCPP_LOG_INFO << fileName2 << "\n";
		String fn = fs[0] + fs[fs.size() - 1];
		if (!FileUtil::existFile(fileName1) || !FileUtil::existFile(fileName2))
		{
			OCPP_LOG_ERROR << fileName2 << "\n";
		}
		CSVToJson_main(fileName1, joinPath(path, U2A("涌浪"), fn));
		CSVToJson_main(fileName2, joinPath(path, U2A("滑坡"), fn));
	}


	//CSVToJson_main(U2A(joinPath("I:\\Project\\2024\\数字三峡\\滑坡\\龚家方滑坡", "landslide thickness all.txt")), 0);
	//CSVToJson_main(U2A(joinPath("I:\\Project\\2024\\数字三峡\\涌浪\\八字门", "wave all as time100年降雨工况.txt")), 0);
	//CSVToJson_main(U2A(joinPath("I:\\Project\\2024\\数字三峡\\涌浪\\八字门", "wave all as time150年降雨工况.txt")), 0);
}
#endif

//涌浪 新180s
#if 0
void  CSVToJson()
{
	String output = "\\\\10.104.207.155\\Cesium\\Assets\\2024\\Sanxia\\yl\\xt";
	String fileName = U2A("I:\\Project\\2024\\数字三峡\\涌浪点位\\新滩\\新滩.txt");
	OCPP_LOG_INFO << fileName << "\n";

	std::ifstream ifs(fileName);
	if (ifs)
	{
		String line;

		uint32 count = 0;
		std::map<uint32, std::vector<double> > mapData;

		while (getline(ifs, line))
		{
			StringUtil::trim(line);
			StringVector strVec = StringUtil::split(line, " ");
			if (strVec.empty())
			{
				break;
			}

			if (strVec.size() != 4)
			{
				OCPP_LOG_ERROR << "line error:" << strVec.size() << "\n";
				break;
			}

			float x = std::stof(strVec[0].c_str());
			float y = std::stof(strVec[1].c_str());
			int t = std::stoi(strVec[2].c_str());
			float z = std::stof(strVec[3].c_str());

			mapData[t].push_back(x);
			mapData[t].push_back(y);
			mapData[t].push_back(z);
			count++;
		}

		for (const auto& [first, second] : mapData)
		{
			OCPP_LOG_INFO << "Time:" << first << "\tnum:" << second.size() << "\n";
			String name = str_format("%d.json", first);
			std::ofstream ofs(joinPath(output, name));

			rapidjson::StringBuffer buffer;
			rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
			writer.StartArray();
			writer.SetMaxDecimalPlaces(8);
			for (const auto& d : second)
			{
				writer.Double(d);
			}
			writer.EndArray();
			ofs << buffer.GetString();
			ofs.close();
		}
	}
}
#endif

#if 0
void  CSVToJson()
{
	String output = "\\\\10.104.207.155\\Cesium\\Assets\\2024\\Qingdao";
	//String fileName = U2A("I:\\Project\\2024\\青岛\\20240704\\20240704000000\\00FM 10020240704000000.csv");
	String fileName = U2A("I:\\Project\\2024\\青岛\\20240705\\20240705000000\\00FM 10020240705000000.csv");
	OCPP_LOG_INFO << fileName << "\n";

	std::ifstream ifs(fileName);
	if (ifs)
	{
		String line;

		uint32 skip = 0;
		uint32 count = 0;
		std::map<uint32, std::vector<double> > mapData;

		String name = "20240705000000.json";

		rapidjson::StringBuffer buffer;
		rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
		writer.StartArray();
		writer.SetMaxDecimalPlaces(8);

		while (getline(ifs, line))
		{
			StringUtil::trim(line);
			if (line == "****") {
				skip++;
			}

			if (skip == 0)
			{
				continue;
			}

			if (skip <= 2)
			{
				skip++;
				continue;
			}

			StringVector strVec = StringUtil::split(line, ",");
			if (strVec.empty())
			{
				break;
			}

			if (strVec.size() != 56)
			{
				OCPP_LOG_ERROR << "line error:" << strVec.size() << "\n";
				return;
			}

			float seconds = std::stof(strVec[0].c_str());
			float nc = std::stof(strVec[28].c_str());
			float ed = std::stof(strVec[31].c_str());

			writer.StartArray();

			writer.Double(seconds);
			writer.Double(nc);
			writer.Double(ed);

			writer.EndArray();
		}

		std::ofstream ofs(joinPath(output, name));

		writer.EndArray();
		ofs << buffer.GetString();
		ofs.close();
	}
}
#endif
